#pragma once
#include <deque>
#include <map>
#include <mutex>
#include <thread>
#include <vector>
#include <conio.h>
#include "Player.h"
#include "Console.h"

using namespace std;
using namespace Course;

class Game
{
private:
	vector<vector<char>> Map;
	int MapArea;
	deque<char> *Player1Queue;
	deque<char> *Player2Queue;
	deque<Position> *MainQueue;
	char *c;

public:
	Game(void)
	{
	}

	Game(int Area, deque<char> &Player1Queue, deque<char> &Player2Queue, deque<Position> &MainQueue)
	{
		MapArea = Area;
		Map = vector<vector<char>>(Area);
		for(int i = 0; i < Area; i++)
		{
			Map[i] = vector<char>(Area);
		}
		for(int Row = 0; Row < MapArea; Row++)
		{
			for(int Column = 0; Column < MapArea; Column++)
				Map[Row][Column] = '.';
		}
		this->Player1Queue = &Player1Queue;
		this->Player2Queue = &Player2Queue;
		this->MainQueue = &MainQueue;
	}

	void Update()
	{
		Position Pos;

		MxGameQueue.lock();
		if(!MainQueue->empty())
		{
			Pos = MainQueue->front();
			MainQueue->pop_front();

			for(int Row = 0; Row < MapArea; Row++)
			{
				for(int Column = 0; Column < MapArea; Column++)
				{
					if(Map[Row][Column] == Pos.Id)
					{
						Map[Row][Column] = '.';
					}
				}
			}
			int x = Pos.XPos;
			int y = Pos.YPos;
			Map[y][x] = Pos.Id;
		}
		MxGameQueue.unlock();
	}

	void PushQueue(char c)
	{
		MxPlayerQueue.lock();
		if(c == 'w' || c == 'a' || c == 's' || c == 'd')
			Player1Queue->push_back(c);
		if(c == 72 || c == 75 || c == 80 || c == 77)
			Player2Queue->push_back(c);
		MxPlayerQueue.unlock();
	}

	void Draw()
	{
		Console::clrscr();
		for(int Row = 0; Row < MapArea; Row++)
		{
			for(int Column = 0; Column < MapArea; Column++)
			{
				cout << (char)Map[Row][Column] << " ";
			}
			cout << endl;
		}
	}

	void operator()()
	{
		char c = ' ';
		if(_kbhit() != 0)
		{
			c = _getch();
		}

		while(c != 'e')
		{
			Draw();
			PushQueue(c);
			c = ' ';
			Update();
			this_thread::sleep_for(chrono::milliseconds(100));
			if(_kbhit() != 0)
			{
				c = _getch();
			}
		}
	}

	~Game(void)
	{
	}
};
